<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="keywords" content="anhoder的进阶日志">
<meta name="description" content="一川烟草，满城风絮。">
<meta name="theme-color" content="#000">
<title>Nginx服务器配置详解 | anhoder的进阶日志</title>
<link rel="shortcut icon" href="/favicon.ico?v=1640406618472">
<link rel="stylesheet" href="/media/css/pisces.css">
<link rel="stylesheet" href="/media/fonts/font-awesome.css">
<link
  href="//fonts.googleapis.com/css?family=Monda:300,300italic,400,400italic,700,700italic|Roboto Slab:300,300italic,400,400italic,700,700italic|Rosario:300,300italic,400,400italic,700,700italic|PT Mono:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext"
  rel="stylesheet" type="text/css">

<link href="/media/hljs/styles/androidstudio.css"
  rel="stylesheet">

<script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/themes/green/pace-theme-minimal.css" rel="stylesheet" />

<link rel="stylesheet" href="/styles/main.css">

<script src="/media/hljs/highlight.js"></script>
<script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.0/velocity.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.0/velocity.ui.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css"
  integrity="sha384-zB1R0rpPzHqg7Kpt0Aljp8JPLqbXI3bhnPWROx27a9N0Ll6ZP/+DiW/UqRcLbRjq" crossorigin="anonymous">


<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.js"
  integrity="sha384-y23I5Q6l+B6vatafAwxRu/0oK/79VlbSz7Q9aiSZUvyWYIYsd+qj+o24G5ZU2zJz" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/contrib/auto-render.min.js"
  integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"
  onload="renderMathInElement(document.body);"></script>



<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-161423102-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag() { dataLayer.push(arguments); }
  gtag('js', new Date());

  gtag('config', 'UA-161423102-1');
</script>


<script>
  var _hmt = _hmt || [];
  (function () {
    var hm = document.createElement("script");
    hm.src = "https://hm.baidu.com/hm.js?bdf14d3cd277bc2dfa9f84d19b36a686";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
  })();
</script>


  <meta name="description" content="Nginx服务器配置详解" />
  <meta name="keywords" content="Nginx" />
</head>

<body>
  <div class="head-top-line"></div>
  <div class="header-box">
    
<div class="pisces">
  <header class="header  ">
    <div class="blog-header box-shadow-wrapper bg-color " id="header">
      <div class="nav-toggle" id="nav_toggle">
        <div class="toggle-box">
          <div class="line line-top"></div>
          <div class="line line-center"></div>
          <div class="line line-bottom"></div>
        </div>
      </div>
      <div class="site-meta">       
        <div class="site-title">
          
            <a href="/" class="brand">
              <span>anhoder的进阶日志</span>
            </a>  
          
        </div>
        
          <p class="subtitle">太阳不热，糖也正适合。</p>
        
      </div>
      <nav class="site-nav" id="site_nav">
        <ul id="nav_ul">
          
            
            
            <li class="nav-item ">
              
              
                
                  <a href="/" target="_self">
                    <i class="fa fa-home"></i> 首页
                  </a>
                
              
            </li>
          
            
            
            <li class="nav-item ">
              
              
                
                  <a href="/archives/" target="_self">
                    <i class="fa fa-archive"></i> 归档
                  </a>
                
              
            </li>
          
            
            
            <li class="nav-item ">
              
              
                
                  <a href="/tags/" target="_self">
                    <i class="fa fa-tags"></i> 标签
                  </a>
                
              
            </li>
          
            
            
            <li class="nav-item ">
              
              
                
                  <a href="/post/about/" target="_self">
                    <i class="fa fa-user"></i> 关于
                  </a>
                
              
            </li>
          
            
            
            <li class="nav-item ">
              
              
                
                  <a href="https://github.com/anhoder/" target="_blank">
                    <i class="fa fa-github"></i> GitHub
                  </a>
                
              
            </li>
          
            
            
            <li class="nav-item ">
              
              
                
                  <a href="/media/excalidraw/" target="_self">
                    <i class="fa fa-picture-o"></i> 制作手绘图
                  </a>
                
              
            </li>
          
          
          
        </ul>
      </nav>
    </div>
  </header>
</div>

<script type="text/javascript"> 
 
  let showNav = true;

  let navToggle = document.querySelector('#nav_toggle'),
  siteNav = document.querySelector('#site_nav');
  
  function navClick() {
    let sideBar = document.querySelector('.sidebar');
    let navUl = document.querySelector('#nav_ul');
    navToggle.classList.toggle('nav-toggle-active');
    siteNav.classList.toggle('nav-menu-active');
    if (siteNav.classList.contains('nav-menu-active')) {
      siteNav.style = "height: " + (navUl.children.length * 42) +"px !important";
    } else {
      siteNav.style = "";
    }
  }

  navToggle.addEventListener('click',navClick);  
</script>
  </div>
  <div class="main-continer">
    
    <div
      class="section-layout pisces ">
      <div class="section-layout-wrapper">
        

<div class="sidebar">
  
    <div class="sidebar-box box-shadow-wrapper bg-color right-motion" id="sidebar">
      
        <div class="post-list-sidebar">
          <div class="sidebar-title">
            <span id="tocSideBar" class="sidebar-title-item sidebar-title-active language" data-lan="index">文章目录</span>
            <span id="metaSideBar" class="sidebar-title-item language" data-lan="preview">站点概览</span>
          </div>
        </div>
      
      <div class="sidebar-body pisces" id="sidebar_body">
        
          
            <div class="post-side-meta" id="post_side_meta">
              
<div class="sidebar-wrapper box-shadow-wrapper bg-color">
  <div class="sidebar-item">
    <img class="site-author-image right-motion" src="/images/avatar.png"/>
    <p class="site-author-name">anhoder</p>
    
  </div>
  <div class="sidebar-item side-item-stat right-motion">
    <div class="sidebar-item-box">
      <a href="/archives/">
        
        <span class="site-item-stat-count">94</span>
        <span class="site-item-stat-name language" data-lan="article">文章</span>
      </a>
    </div>
    <div class="sidebar-item-box">
      <a href="">
        <span class="site-item-stat-count">27</span>
        <span class="site-item-stat-name language" data-lan="category">分类</span>
      </a>
    </div>
    <div class="sidebar-item-box">
      <a href="/tags/">
        <span class="site-item-stat-count">27</span>
        <span class="site-item-stat-name language" data-lan="tag">标签</span>
      </a>
    </div>
  </div>
  
    
  
  
    <div class="sidebar-item sidebar-item-social">
      <div class="social-item">
        
          
            <a href="https://github.com/anhoder">
              <i class="fa fa-github-alt" title="GitHub"></i>
            </a>
          
            <a href="https://twitter.com/Alan_Albert_">
              <i class="fa fa-twitter" title="Twitter"></i>
            </a>
          
            <a href="https://weibo.com/u/5794659803">
              <i class="fa fa-weibo" title="Weibo"></i>
            </a>
          
            <a href="mailto:anhoder@88.com">
              <i class="fa fa-envelope" title="Email"></i>
            </a>
          
            <a href="https://stackoverflow.com/users/9723854/alan">
              <i class="fa fa-stack-overflow" title="StackOverflow"></i>
            </a>
          
        
        
          
            <a class="social-img" href="#">
              <img src="/media/images/custom-array-imgSocials-1617614181832-socialImg.png" />
              <i class="fa fa-weixin" title="微信公众号" ></i>
            </a>
          
        
      </div>
    </div>
  

  



</div>
            </div>
            <div class="post-toc sidebar-body-active" id="post_toc" style="opacity: 1;">
              <div class="toc-box right-motion">
  <div class="toc-wrapper  auto"
    id="toc_wrapper">
    <ul class="markdownIt-TOC">
<li>
<ul>
<li><a href="#%E4%B8%80-location%E8%A7%84%E5%88%99">一、location规则</a></li>
<li><a href="#%E4%BA%8C-rewrite%E8%A7%84%E5%88%99">二、rewrite规则</a>
<ul>
<li><a href="#1-%E6%A0%87%E5%BF%97%E4%BD%8D">1、标志位</a></li>
<li><a href="#2-if%E6%8C%87%E4%BB%A4">2、if指令</a></li>
<li><a href="#3-nginx%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F">3、Nginx全局变量</a></li>
</ul>
</li>
<li><a href="#%E4%B8%89-upstream%E6%A8%A1%E5%9D%97%E4%B8%8E%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1">三、upstream模块与负载均衡</a>
<ul>
<li><a href="#%E9%85%8D%E7%BD%AE%E6%AD%A5%E9%AA%A4">配置步骤</a></li>
<li><a href="#%E8%AF%B7%E6%B1%82%E5%88%86%E9%85%8D%E7%AD%96%E7%95%A5">请求分配策略</a>
<ul>
<li><a href="#1-%E8%BD%AE%E8%AF%A2">① 轮询</a></li>
<li><a href="#2-weight%E6%9D%83%E9%87%8D">② weight权重</a></li>
<li><a href="#3-ip_hash">③ ip_hash</a></li>
<li><a href="#4-fair">④ fair</a></li>
</ul>
</li>
<li><a href="#5-url_hash">⑤ url_hash</a></li>
<li><a href="#%E7%8A%B6%E6%80%81%E5%80%BC">状态值</a></li>
<li><a href="#%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9Fsession%E7%9A%84%E5%A4%84%E7%90%86%E6%96%B9%E6%B3%95">分布式系统session的处理方法</a></li>
</ul>
</li>
<li><a href="#%E5%9B%9B-events%E4%BA%8B%E4%BB%B6%E6%A8%A1%E5%9E%8B-%E9%98%BB%E5%A1%9E%E9%9D%9E%E9%98%BB%E5%A1%9E%E5%92%8C%E5%90%8C%E6%AD%A5%E5%BC%82%E6%AD%A5">四、Events事件模型、阻塞/非阻塞和同步/异步</a>
<ul>
<li><a href="#%E9%98%BB%E5%A1%9E%E9%9D%9E%E9%98%BB%E5%A1%9E%E4%B8%8E%E5%90%8C%E6%AD%A5%E5%BC%82%E6%AD%A5">阻塞/非阻塞与同步/异步</a>
<ul>
<li><a href="#%E9%98%BB%E5%A1%9Eio-%E9%9D%9E%E9%98%BB%E5%A1%9Eio">阻塞I/O、非阻塞I/O</a></li>
<li><a href="#%E5%90%8C%E6%AD%A5io-%E5%BC%82%E6%AD%A5io">同步I/O、异步I/O</a></li>
<li><a href="#%E5%85%B3%E7%B3%BB">关系</a></li>
</ul>
</li>
<li><a href="#%E6%A0%87%E5%87%86%E4%BA%8B%E4%BB%B6%E6%A8%A1%E5%9E%8B">标准事件模型</a>
<ul>
<li><a href="#read">read</a></li>
<li><a href="#select">select</a></li>
<li><a href="#poll">poll</a></li>
</ul>
</li>
<li><a href="#%E9%AB%98%E6%95%88%E4%BA%8B%E4%BB%B6%E6%A8%A1%E5%9E%8B">高效事件模型</a>
<ul>
<li><a href="#epoll">Epoll</a></li>
<li><a href="#kqueue">Kqueue</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E4%BA%94-nginx%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6-%E6%B3%A8%E9%87%8A">五、Nginx配置文件 + 注释</a></li>
</ul>
</li>
</ul>

  </div>
</div>

<script>

  let lastTop = 0, lList = [], hList = [], postBody, lastIndex = -1;
  let active = 'active-show', activeClass = 'active-current';
  let tocWrapper = document.querySelector('#toc_wrapper');
  let tocContent = tocWrapper.children[0];
  let autoNumber = tocWrapper && tocWrapper.classList.contains('auto-number');

  function addTocNumber(elem, deep) {
    if (!elem) {
      return;
    }
    let prop = elem.__proto__;

    if (prop === HTMLUListElement.prototype) {
      for (let i = 0; i < elem.children.length; i++) {
        addTocNumber(elem.children[i], deep + (i + 1) + '.');
      }
    } else if (prop === HTMLLIElement.prototype) {
      // 保存li元素
      if (elem.children[0] && elem.children[0].__proto__ === HTMLAnchorElement.prototype) {
        lList.push(elem);
      }
      for (let i = 0; i < elem.children.length; i++) {
        let cur = elem.children[i];
        if (cur.__proto__ === HTMLAnchorElement.prototype) {
          if (autoNumber) {
            cur.text = deep + ' ' + cur.text;
          }
        } else if (cur.__proto__ === HTMLUListElement.prototype) {
          addTocNumber(cur, deep);
        }
      }
    }
  }

  function removeParentActiveClass() {
    let parents = tocContent.querySelectorAll('.' + active)
    parents.forEach(function (elem) {
      elem.classList.remove(active);
    });
  }

  function addActiveClass(index) {
    if (index >= 0 && index < hList.length) {
      lList[index].classList.add(activeClass);
    }
  }

  function removeActiveClass(index) {
    if (index >= 0 && index < hList.length) {
      lList[index].classList.remove(activeClass);
    }
  }

  function addActiveLiElemment(elem, parent) {
    if (!elem || elem === parent) {
      return;
    } else {
      if (elem.__proto__ === HTMLLIElement.prototype) {
        elem.classList.add(active);
      }
      addActiveLiElemment(elem.parentElement, parent);
    }
  }

  function showToc() {
    if (tocWrapper) {
      postBody = document.querySelector('#post_body');
      for (let i = 0; i < postBody.children.length; i++) {
        if (postBody.children[i].__proto__ === HTMLHeadingElement.prototype) {
          hList.push(postBody.children[i]);
        }
      }
      if (tocWrapper.classList.contains('compress')) {
        tocContent.classList.add('closed');
      } else if (tocWrapper.classList.contains('no_compress')) {
        tocContent.classList.add('expanded');
      } else {
        if (hList.length > 10) {
          active = 'active-hidden'
          tocContent.classList.add('closed');
        } else {
          tocContent.classList.add('expanded');
        }
      }
    }
  }

  (function () {
    // 处理不是从#一级标题开始目录
    if (tocContent.children.length === 1 && tocContent.children[0].__proto__ === HTMLLIElement.prototype) {
      let con = tocContent.children[0].children[0];
      tocContent.innerHTML = con.innerHTML;
    }
    let markdownItTOC = document.querySelector('.markdownIt-TOC');
    let innerHeight = window.innerHeight;
    markdownItTOC.style = `max-height: ${innerHeight - 80 > 0 ? innerHeight - 80 : innerHeight}px`
    addTocNumber(tocContent, '');
  })();

  document.addEventListener('scroll', function (e) {
    if (lList.length <= 0) {
      return;
    }
    let scrollTop = document.scrollingElement.scrollTop + 10;
    let dir;

    if (lastTop - scrollTop > 0) {
      dir = 'up';
    } else {
      dir = 'down';
    }

    lastTop = scrollTop;
    if (scrollTop <= 0) {
      if (lastIndex >= 0 && lastIndex < hList.length) {
        lList[lastIndex].classList.remove(activeClass);
      }
      return;
    }

    let current = 0, hasFind = false;
    for (let i = 0; i < hList.length; i++) {
      if (hList[i].offsetTop > scrollTop) {
        current = i;
        hasFind = true;
        break;
      }
    }
    if (!hasFind && scrollTop > lList[lList.length - 1].offsetTop) {
      current = hList.length - 1;
    } else {
      current--;
    }
    if (dir === 'down') {
      if (current > lastIndex) {
        addActiveClass(current);
        removeActiveClass(lastIndex)
        lastIndex = current;
        removeParentActiveClass();
        lList[current] && addActiveLiElemment(lList[current].parentElement, tocContent);
      }
    } else {
      if (current < lastIndex) {
        addActiveClass(current);
        removeActiveClass(lastIndex);
        lastIndex = current;
        removeParentActiveClass();
        lList[current] && addActiveLiElemment(lList[current].parentElement, tocContent);
      }
    }
  });


  window.addEventListener('load', function () {
    showToc();
    document.querySelector('#sidebar').style = 'display: block;';
    tocWrapper.classList.add('toc-active');
    setTimeout(function () {
      if ("createEvent" in document) {
        let evt = document.createEvent("HTMLEvents");
        evt.initEvent("scroll", false, true);
        document.dispatchEvent(evt);
      }
      else {
        document.fireEvent("scroll");
      }
    }, 500)
  })

</script>
            </div>
          
        
      </div>
    </div>
  
</div>
<script>
  const SIDEBAR_TITLE_ACTIVE = 'sidebar-title-active';
  const SIDEBAR_BODY_ACTIVE = 'sidebar-body-active';
  const SLIDE_UP_IN = 'slide-up-in';

  let sidebar = document.querySelector('#sidebar'),
  tocSideBar = document.querySelector('#tocSideBar'),
  metaSideBar = document.querySelector('#metaSideBar'),
  postToc = document.querySelector('#post_toc'),
  postSiteMeta = document.querySelector('#post_side_meta'),
  sidebarTitle = document.querySelector('.sidebar-title'),
  sidebarBody = document.querySelector('#sidebar_body');

  tocSideBar && tocSideBar.addEventListener('click', (e) => {
    toggleSidebar(e);
  });

  metaSideBar && metaSideBar.addEventListener('click', (e) => {
    toggleSidebar(e);
  });

  function toggleSidebar(e) {
    let currentTitle = document.querySelector("."+SIDEBAR_TITLE_ACTIVE);
    if (currentTitle == e.srcElement) {
      return ;
    }
    let current, showElement, hideElement;
    if (e.srcElement == metaSideBar) {
      showElement = postSiteMeta;
      hideElement = postToc;
    } else if (e.srcElement == tocSideBar){
      showElement = postToc;
      hideElement = postSiteMeta;
    }
    currentTitle.classList.remove(SIDEBAR_TITLE_ACTIVE);
    e.srcElement.classList.add(SIDEBAR_TITLE_ACTIVE);

    window.Velocity(hideElement, 'stop');
    window.Velocity(hideElement, 'transition.slideUpOut', {
      display: 'none',
      duration: 200,
      complete: function () {
        window.Velocity(showElement, 'transition.slideDownIn', {
          duration: 200
        });
      }
    })
    hideElement.classList.remove(SIDEBAR_BODY_ACTIVE);
    showElement.classList.add(SIDEBAR_BODY_ACTIVE);
  }

  postToc && postToc.addEventListener('transitionend', function() {
    this.classList.remove(SLIDE_UP_IN);
  });

  if (sidebarBody) {
    if (sidebarBody.classList.contains('pisces') || sidebarBody.classList.contains('gemini')) {
      let hasFix = false;
      let scrollEl = document.querySelector('.main-continer');
      let limitTop = document.querySelector('#nav_ul').children.length * 42 + 162;
      window.addEventListener('scroll', function(e) {
        if (document.scrollingElement.scrollTop >= limitTop) {
          if (!hasFix) {
            sidebar.classList.add('sidebar-fixed');
            hasFix = true;
          }
        } else {
          if (hasFix) {
            sidebar.classList.remove('sidebar-fixed');
            hasFix = false;
          }
        }
      });
    }
  }
  
</script>
        <div class="section-box box-shadow-wrapper">
          <div class="section bg-color post post-page">
            <section class="post-header">
  <h1 class="post-title">
    <a class="post-title-link" href="/post/nQ_auU4ob/">
      Nginx服务器配置详解
    </a>
  </h1>
  <div class="post-meta">
    
    <span class="meta-item pc-show">
      <i class="fa fa-calendar-o"></i>
      <span class="language" data-lan="publish">发布于</span>
      <span class="publish-time" data-t="2018-10-15 19:02:38">2018-10-15</span>
      <span class="post-meta-divider pc-show">|</span>
    </span>
    
    <span class="meta-item">
      <i class="fa fa-folder-o"></i>
      <span class="pc-show language" data-lan="category-in">分类于</span>
      
      
      <a href="/tag/GEB4m1_Wa/">
        <span>Nginx</span>
      </a>
      
      
    </span>
    <span class="post-meta-divider">|</span>
    
    <span class="meta-item">
      <i class="fa fa-clock-o"></i>
      <span>17<span class="language" data-lan="minute">分钟</span></span>
    </span>
    <span class="meta-item">
      <span class="post-meta-divider">|</span>
      <i class="fa fa-file-word-o"></i>
      <span>4230<span class="pc-show language" data-lan="words">字数</span></span>
    </span>
    
  </div>
</section>
            <div class="post-body next-md-body" id="post_body">
              <!-- more -->
<p>Nginx的配置结构大致如下：</p>
<pre><code class="language-conf">events {
  use epoll;
}

http {
  #http
  server {
    listen 80;
    ...
    
    location / {
        if() {
          ...
        }
    }
    ...
  }
  
  #https
  server {
    listen 443;
    ...
  }
  
  ...
}
</code></pre>
<h2 id="一-location规则">一、location规则</h2>
<p>格式如下：</p>
<pre><code class="language-conf">location [ = | ^~ | ~ | ~* | / ] [字符串 | 正则表达式] {
    [相关处理]
}
</code></pre>
<ul>
<li>① = 表示精确匹配，例如：location = / {...}表示只匹配根目录的请求，后加字符串的不能匹配</li>
<li>② ^~ 表示匹配URI以常规字符串开头的请求，不是正则匹配，例如：location ^~ /home {...}只能匹配/home/index、/home/other/other等以其开头的请求</li>
<li>③ ~ 表示区分大小写的正则匹配</li>
<li>④ ~* 表示不区分大小写的正则匹配</li>
<li>⑤ / 表示通用匹配，任何请求都会匹配</li>
</ul>
<p>优先级：(location =) &gt; (location 完整路径) &gt; (location ^~) &gt; (location <sub>,</sub>*) &gt; (location 部分起始路径) &gt; (location /)</p>
<h2 id="二-rewrite规则">二、rewrite规则</h2>
<p>作用：使用nginx的全局变量及自定义变量实现URL的重写及重定向（放在server、location、if中）。</p>
<p>rewrite和location具有相似之处，其区别在于：</p>
<blockquote>
<p>location主要用于访问控制、反向代理<br>
rewrite主要用于实现URL的重写、跳转</p>
</blockquote>
<p>rewrite规则格式如下：</p>
<pre><code class="language-conf">rewrite 正则表达式 目标URL 标志位;
</code></pre>
<p>例如：</p>
<pre><code class="language-conf">server {
  rewrite /(.*)$ /index.php/$1 last; # 隐藏URL中的index.php

  location ~ (.*)/index\.php$ {
    ...
  }
}
# http://www.xxxx.com/home/controller/action/param请求到来
# ① server中的rewrite匹配到该请求，并将URL重写为http://www.xxxx.com/index.php/home/controller/action/param
# ② location匹配到重写后的URL（http://www.xxxx.com/index.php/home/controller/action/param），执行location中的操作
</code></pre>
<h3 id="1-标志位">1、标志位</h3>
<ul>
<li>① last 表示完成rewrite</li>
<li>② break 表示停止当前虚拟主机的后续rewrite指令</li>
<li>③ redirect 表示返回302临时重定向，地址栏会显示跳转后的地址</li>
<li>④ permanent 表示返回301永久重定向，地址栏显示跳转后的地址</li>
</ul>
<h3 id="2-if指令">2、if指令</h3>
<p>格式如下：</p>
<pre><code class="language-conf">if(condition) {
  ...
}
</code></pre>
<p>需要注意的是：</p>
<ul>
<li>① 判断是否相等使用 = 或 !=</li>
<li>② ~ 正则表达式匹配，~* 不区分大小写的匹配，!~ 区分大小写的不匹配</li>
<li>③ -f 和 !-f 用于判断是否存在文件</li>
<li>④ -d 和 !-d 用来判断是否存在目录</li>
<li>⑤ -e 和 !-e 用来判断是否存在文件或目录</li>
<li>⑥ -x 和 !-x 用来判断文件是否可执行</li>
</ul>
<p>if使用用例：</p>
<pre><code class="language-conf">if ($http_user_agent ~ MSIE) {
    ...
}
</code></pre>
<h3 id="3-nginx全局变量">3、Nginx全局变量</h3>
<ul>
<li><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>a</mi><mi>r</mi><mi>g</mi><mi>s</mi><mi mathvariant="normal">：</mi><mi mathvariant="normal">这</mi><mi mathvariant="normal">个</mi><mi mathvariant="normal">变</mi><mi mathvariant="normal">量</mi><mi mathvariant="normal">等</mi><mi mathvariant="normal">于</mi><mi mathvariant="normal">请</mi><mi mathvariant="normal">求</mi><mi mathvariant="normal">行</mi><mi mathvariant="normal">中</mi><mi mathvariant="normal">的</mi><mi mathvariant="normal">参</mi><mi mathvariant="normal">数</mi><mi mathvariant="normal">，</mi><mi mathvariant="normal">同</mi></mrow><annotation encoding="application/x-tex">args：这个变量等于请求行中的参数，同</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathdefault">a</span><span class="mord mathdefault" style="margin-right:0.02778em;">r</span><span class="mord mathdefault" style="margin-right:0.03588em;">g</span><span class="mord mathdefault">s</span><span class="mord cjk_fallback">：</span><span class="mord cjk_fallback">这</span><span class="mord cjk_fallback">个</span><span class="mord cjk_fallback">变</span><span class="mord cjk_fallback">量</span><span class="mord cjk_fallback">等</span><span class="mord cjk_fallback">于</span><span class="mord cjk_fallback">请</span><span class="mord cjk_fallback">求</span><span class="mord cjk_fallback">行</span><span class="mord cjk_fallback">中</span><span class="mord cjk_fallback">的</span><span class="mord cjk_fallback">参</span><span class="mord cjk_fallback">数</span><span class="mord cjk_fallback">，</span><span class="mord cjk_fallback">同</span></span></span></span>query_string</li>
<li>$content_length：请求头中的Content-length字段。</li>
<li>$content_type：请求头中的Content-Type字段。</li>
<li>$document_root：当前请求在root指令中指定的值。</li>
<li>$host：请求主机头字段，否则为服务器名称。</li>
<li>$http_user_agent：客户端agent信息</li>
<li>$http_cookie：客户端cookie信息</li>
<li>$limit_rate：这个变量可以限制连接速率。</li>
<li>$request_method：客户端请求的动作，通常为GET或POST。</li>
<li>$remote_addr：客户端的IP地址。</li>
<li>$remote_port：客户端的端口。</li>
<li>$remote_user：已经经过Auth Basic Module验证的用户名。</li>
<li>$request_filename：当前请求的文件路径，由root或alias指令与URI请求生成。</li>
<li>$scheme：HTTP方法（如http，https）。</li>
<li>$server_protocol：请求使用的协议，通常是HTTP/1.0或HTTP/1.1。</li>
<li>$server_addr：服务器地址，在完成一次系统调用后可以确定这个值。</li>
<li>$server_name：服务器名称。</li>
<li>$server_port：请求到达服务器的端口号。</li>
<li>$request_uri：包含请求参数的原始URI，不包含主机名，如：”/foo/bar.php?arg=baz”。</li>
<li><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>u</mi><mi>r</mi><mi>i</mi><mi mathvariant="normal">：</mi><mi mathvariant="normal">不</mi><mi mathvariant="normal">带</mi><mi mathvariant="normal">请</mi><mi mathvariant="normal">求</mi><mi mathvariant="normal">参</mi><mi mathvariant="normal">数</mi><mi mathvariant="normal">的</mi><mi mathvariant="normal">当</mi><mi mathvariant="normal">前</mi><mi>U</mi><mi>R</mi><mi>I</mi><mi mathvariant="normal">，</mi></mrow><annotation encoding="application/x-tex">uri：不带请求参数的当前URI，</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">u</span><span class="mord mathdefault" style="margin-right:0.02778em;">r</span><span class="mord mathdefault">i</span><span class="mord cjk_fallback">：</span><span class="mord cjk_fallback">不</span><span class="mord cjk_fallback">带</span><span class="mord cjk_fallback">请</span><span class="mord cjk_fallback">求</span><span class="mord cjk_fallback">参</span><span class="mord cjk_fallback">数</span><span class="mord cjk_fallback">的</span><span class="mord cjk_fallback">当</span><span class="mord cjk_fallback">前</span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mord mathdefault" style="margin-right:0.00773em;">R</span><span class="mord mathdefault" style="margin-right:0.07847em;">I</span><span class="mord cjk_fallback">，</span></span></span></span>uri不包含主机名，如”/foo/bar.html”。</li>
<li><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>d</mi><mi>o</mi><mi>c</mi><mi>u</mi><mi>m</mi><mi>e</mi><mi>n</mi><msub><mi>t</mi><mi>u</mi></msub><mi>r</mi><mi>i</mi><mi mathvariant="normal">：</mi><mi mathvariant="normal">与</mi></mrow><annotation encoding="application/x-tex">document_uri：与</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.84444em;vertical-align:-0.15em;"></span><span class="mord mathdefault">d</span><span class="mord mathdefault">o</span><span class="mord mathdefault">c</span><span class="mord mathdefault">u</span><span class="mord mathdefault">m</span><span class="mord mathdefault">e</span><span class="mord mathdefault">n</span><span class="mord"><span class="mord mathdefault">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">u</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathdefault" style="margin-right:0.02778em;">r</span><span class="mord mathdefault">i</span><span class="mord cjk_fallback">：</span><span class="mord cjk_fallback">与</span></span></span></span>uri相同。</li>
</ul>
<h2 id="三-upstream模块与负载均衡">三、upstream模块与负载均衡</h2>
<p>Nginx的反向代理是其出色的特点之一，通过反向代理可以实现负载均衡，将请求分发到其他服务器。而upstream节点就是配置反向代理的关键所在。</p>
<h3 id="配置步骤">配置步骤</h3>
<p>① 在http节点下加入upstream节点：</p>
<pre><code class="language-conf">upstream upstreamName {
    server ip1:port1;
    server ip2:port2;
    ...
}
</code></pre>
<p>② 在server节点下的location节点中，将相应的请求通过proxy_pass转发到http://upstreamName下：</p>
<pre><code class="language-conf">location / {
    ...
    proxy_pass http://upstreamName;
    ...
}
</code></pre>
<p>至此，负载均衡已经配置完毕，Nginx会根据轮询的策略将请求按时间顺序逐一分配到不同的后端服务器上。</p>
<p>当然，还存在其他的分配策略。</p>
<h3 id="请求分配策略">请求分配策略</h3>
<h4 id="1-轮询">① 轮询</h4>
<p>默认情况下，Nginx使用轮询的方式进行请求的分配，这种方式虽然配置简单，但缺点在于可靠性不高、请求分发不均衡。</p>
<h4 id="2-weight权重">② weight权重</h4>
<p>在upstream节点中指定server的weight权重，Nginx会根据每个服务器的权重调整分发请求的几率，weight与分发请求的几率成正比，例如：</p>
<pre><code class="language-conf">upstream upstreamName{
    server ip1:port1 weight=1;
    server ip2:port2 weight=2;
    # 转发请求给ip2服务器的几率是转发给ip1服务器的两倍
    ...
}
</code></pre>
<h4 id="3-ip_hash">③ ip_hash</h4>
<p>每个请求都按照访问ip的hash结果进行分配，即访问ip与服务器绑定，同一个用户的请求都会固定转发到一台服务器上进行处理（该方法可以用于解决分布式session不一致的问题）。使用方法：</p>
<pre><code class="language-conf">upstream upstreamName{
    ip_hash;
    server ip1:port1;
    server ip2:port2;
    ...
}
</code></pre>
<h4 id="4-fair">④ fair</h4>
<p>使用后端服务器的响应时间作为依据，响应时间短的服务器分配到更多的请求。</p>
<pre><code class="language-conf">upstream upstreamName{
    fair;
    server ip1:port1;
    server ip2:port2;
}
</code></pre>
<h3 id="5-url_hash">⑤ url_hash</h3>
<p>通过访问url的hash结果来分配请求，让url定向到同一个后端服务器：</p>
<pre><code class="language-conf">upstream upstreamName{
    server ip1:port1;
    server ip2:port2;
    hash $request_uri;  
    hash_method crc32;  # 计算hash时使用的hash算法
    ### 使用hash后，不能使用weight等其他参数
}
</code></pre>
<h3 id="状态值">状态值</h3>
<p>upstream节点中，可以为每一个设备设置状态值，如下：</p>
<blockquote>
<p>down: 表示当前的server不参与负载均衡<br>
weight: weight越大，收到的请求就越多<br>
max_fails: 允许请求失败的最大次数，当超过该值时，返回proxy_next_upstream模块定义的错误<br>
fail_timeout: 达到max_fails次失败时，暂停的时间<br>
backup: 后备服务器，当其他全部的非backup机器down或者忙的时候，请求backup机器</p>
</blockquote>
<p>使用方法：</p>
<pre><code class="language-conf">upstream upstreamName{
    server ip1:port1 down;
    server ip2:port2 weight=2;
    server ip3:port3 backup;
}
</code></pre>
<h3 id="分布式系统session的处理方法">分布式系统session的处理方法</h3>
<p>① session复制：当某一台服务器的session发生改变时，将session的改变复制到其他所有服务器上（毫无疑问，该方法的性能较低）<br>
② 请求ip与服务器绑定：客户端的ip与服务器绑定在一起，同一用户的请求都转发到同一台机器上进行处理<br>
③ 将session信息存放在MySQL等数据库中<br>
④ 将session存放在Redis、memcached内存数据库中</p>
<h2 id="四-events事件模型-阻塞非阻塞和同步异步">四、Events事件模型、阻塞/非阻塞和同步/异步</h2>
<p>Nginx的I/O模型包括标准事件模型、高效事件模型。</p>
<h3 id="阻塞非阻塞与同步异步">阻塞/非阻塞与同步/异步</h3>
<p>我相信有很大一部分人会把非阻塞I/O和异步I/O混为一谈，因为我在写这篇博客之前也是这么认为的。</p>
<h4 id="阻塞io-非阻塞io">阻塞I/O、非阻塞I/O</h4>
<blockquote>
<p>阻塞I/O：应用程序需要等待I/O完成后才返回结果，阻塞I/O造成CPU等待I/O，CPU的能力不能得到充分利用。<br>
非阻塞I/O：在调用后直接返回，不等待I/O完成，但之后需要使用轮询或者其他事件模型（select、poll、epoll、kqueue）来判断是否完成I/O，若I/O完成，则执行后续操作。<br>
在非阻塞I/O返回后，CPU的时间片可以用来处理其他事务。</p>
</blockquote>
<h4 id="同步io-异步io">同步I/O、异步I/O</h4>
<blockquote>
<p>同步I/O：导致请求进程阻塞，直到I/O操作完成；<br>
异步I/O：不导致请求进程阻塞，I/O完成发出通知</p>
</blockquote>
<h4 id="关系">关系</h4>
<p>阻塞I/O、非阻塞I/O都属于同步I/O，用知乎的一个回答来说明吧：</p>
<blockquote>
<p><em>作者：愚抄</em><br>
<em>链接：https://www.zhihu.com/question/19732473/answer/23434554</em><br>
<em>来源：知乎</em></p>
<p>老张爱喝茶，废话不说，煮开水。<br>
出场人物：老张，水壶两把（普通水壶，简称水壶；会响的水壶，简称响水壶）。</p>
<p>1 老张把水壶放到火上，立等水开。（同步阻塞）<br>
老张觉得自己有点傻<br>
2 老张把水壶放到火上，去客厅看电视，时不时去厨房看看水开没有。（同步非阻塞）<br>
老张还是觉得自己有点傻，于是变高端了，买了把会响笛的那种水壶。水开之后，能大声发出嘀~~~~的噪音。<br>
3 老张把响水壶放到火上，立等水开。（异步阻塞）<br>
老张觉得这样傻等意义不大<br>
4 老张把响水壶放到火上，去客厅看电视，水壶响之前不再去看它了，响了再去拿壶。（异步非阻塞）<br>
老张觉得自己聪明了。</p>
<p>所谓同步异步，只是对于水壶而言。<br>
普通水壶，同步；响水壶，异步。<br>
虽然都能干活，但响水壶可以在自己完工之后，提示老张水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己（情况2中），造成老张效率的低下。</p>
<p>所谓阻塞非阻塞，仅仅对于老张而言。<br>
立等的老张，阻塞；看电视的老张，非阻塞。<br>
情况1和情况3中老张就是阻塞的，媳妇喊他都不知道。虽然3中响水壶是异步的，可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的，这样才能发挥异步的效用。<br>
——来源网络，作者不明。</p>
</blockquote>
<h3 id="标准事件模型">标准事件模型</h3>
<p>如果当前系统不存在更高效的方法，则使用标准事件模型select或poll</p>
<h4 id="read">read</h4>
<p>read是最原始、最低效的事件模型。其通过重复调用来检查I/O状态，即轮询。</p>
<h4 id="select">select</h4>
<p>select是read的改进版，它通过轮询监视文件描述符集合，来获取发生变化的文件描述符（集合中的文件描述符会被内核进行标志位修改）。<br>
缺点：① 文件描述符的数量具有限制；② 当文件描述符数量增多时，采取轮询的性能会降低；</p>
<h4 id="poll">poll</h4>
<p>poll的处理机制与select类似，区别在于poll使用链表，而不是数组，避免了长度限制。但文件描述符较多时，性能还是十分低下。</p>
<h3 id="高效事件模型">高效事件模型</h3>
<h4 id="epoll">Epoll</h4>
<p><em>使用于Linux内核2.6版本及以后的系统</em><br>
相对于poll，epoll只会处理发生改变的文件描述符，这样避免了不必要的事件处理，提升了性能及效率。</p>
<h4 id="kqueue">Kqueue</h4>
<p><em>使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X</em><br>
实现方式与epoll类似，不过它仅在FreeBSD系统下存在。</p>
<h2 id="五-nginx配置文件-注释">五、Nginx配置文件 + 注释</h2>
<pre><code class="language-conf"># Nginx的用户和组
user www www;

# 工作进程的数目
worker_processes auto;

# 错误日志存放位置，格式为：error_log 文件路径 错误级别（debug | info | notice | warn | error | crit | alert | emerg），级别越高记录的信息越少
error_log /wwwlogs/error_nginx.log crit;

# 进程标识符
pid /var/run/nginx.pid;

# 进程可以打开最大描述符的数目
worker_rlimit_nofile 51200;

events {
  # 使用的I/O模型（epoll、kqueue、select、poll etc.）
  use epoll;

  # 若该项设置为off，当一个请求到来时，所有休眠的worker进程都会被唤醒，来争夺这个请求，但只有一个进程可以处理该请求，其他未获得请求的进程继续进入休眠，这就是惊群现象，会造成极大地资源浪费
  # 该项设置为on后，Nginx规定同一时刻只能有唯一一个持有mutex锁的worker进程会接受并处理请求
  accept_mutex on;

  # worker进程的等待时间，过了等待时间后，下一个worker进程取得mutex锁
  accept_mutex_delay 500ms;

  # 每个工作进程的最大连接数，与前面的
  worker_connections 51200;

  # 让worker进程尽可能多的接受请求
  # 设置为on时，让worker进程一次性地接受监听队列里的所有请求；设置为off则必须一个一个地接受监听队列里的请求
  multi_accept on;
}

# http服务器
http {
  # 包含mime.types文件，该文件为MIME类型映射表（例如图片、文本、视频等）
  # types {
  #  text/html                                        html htm shtml;
  #  text/css                                         css;
  #  text/xml                                         xml;
  #  image/gif                                        gif;
  #  image/jpeg                                       jpeg jpg;
  #  application/javascript                           js;
  #  application/atom+xml                             atom;
  #  application/rss+xml                              rss;
  #  ......
  # }
  include mime.types;

  # 指定默认MIME类型（application/octet-stream为普通的文件流，浏览器会提示用户下载）
  default_type application/octet-stream;

  # 保存服务器名字的Hash表大小（若增加多个域名后无法启动，可能需要将该项适当调大，并保持为处理器缓存大小的倍数）
  server_names_hash_bucket_size 128;
  # 服务器最大个数
  server_names_hash_max_size 512;

  # 客户端请求头部的缓存区大小
  client_header_buffer_size 32k;
  # nginx默认使用client_header_buffer_size来读取header的值，若header过大，则使用large_client_header_buffers来读取
  large_client_header_buffers 4 32k;

  # 客户端请求body的最大值（nginx上传文件的大小）
  client_max_body_size 1024m;
  # 客户端请求body缓冲区大小
  client_body_buffer_size 10m;

  # sendfile指令指定 nginx 是否调用sendfile 函数（zero copy 方式）来输出文件，对于普通应用，必须设为on。如果用来进行下载等应用磁盘IO重负载应用，可设置为off，以平衡磁盘与网络IO处理速度，降低系统uptime。
  sendfile on;
  # 允许或禁止使用socke的TCP_CORK的选项，此选项仅在使用sendfile的时候使用
  tcp_nopush on;

  # keep-alive超时时间
  keepalive_timeout 120;

  # 开启或关闭nginx的版本信息 
  server_tokens off;

  # 提高数据的实时响应性，仅在将连接转变为长连接的时候才被启用（在upstream发送响应到客户端时也会启用）
  tcp_nodelay on;

  # fastcgi相关配置
  fastcgi_connect_timeout 300;
  fastcgi_send_timeout 300;
  fastcgi_read_timeout 300;
  fastcgi_buffer_size 64k;
  fastcgi_buffers 4 64k;
  fastcgi_busy_buffers_size 128k;
  fastcgi_temp_file_write_size 128k;
  fastcgi_intercept_errors on;

  # Gzip压缩
  gzip on;
  # 16 8k代表以8k为单位，按照原始数据大小以8k为单位的16倍申请内存
  gzip_buffers 16 8k;
  # 压缩级别，等级越高，消耗CPU越多
  gzip_comp_level 6;
  # 设置支持http协议的最小压缩版本
  gzip_http_version 1.1;
  # 允许压缩页面的最小字节数
  gzip_min_length 256;
  # Nginx作为反向代理的时候启用，开启或者关闭后端服务器返回的结果，匹配的前提是后端服务器必须要返回包含&quot;Via&quot;的 header头。
  # off - 关闭所有的代理结果数据的压缩
  # expired - 启用压缩，如果header头中包含 &quot;Expires&quot; 头信息
  # no-cache - 启用压缩，如果header头中包含 &quot;Cache-Control:no-cache&quot; 头信息
  # no-store - 启用压缩，如果header头中包含 &quot;Cache-Control:no-store&quot; 头信息
  # private - 启用压缩，如果header头中包含 &quot;Cache-Control:private&quot; 头信息
  # no_last_modified - 启用压缩,如果header头中不包含 &quot;Last-Modified&quot; 头信息
  # no_etag - 启用压缩 ,如果header头中不包含 &quot;ETag&quot; 头信息
  # auth - 启用压缩 , 如果header头中包含 &quot;Authorization&quot; 头信息
  # any - 无条件启用压缩
  gzip_proxied any;
  # 在http头文件中加个“Vary: Accept-Encoding”，给代理服务器用的，有的浏览器支持压缩，有的不支持所以避免浪费不支持的也压缩，所以根据客户端的HTTP头来判断，是否需要压缩
  gzip_vary on;
  # 压缩的MIME类型
  gzip_types
    text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
    text/javascript application/javascript application/x-javascript
    text/x-json application/json application/x-web-app-manifest+json
    text/css text/plain text/x-component
    font/opentype application/x-font-ttf application/vnd.ms-fontobject
    image/x-icon;
  gzip_disable &quot;MSIE [1-6]\.(?!.*SV1)&quot;;

  #If you have a lot of static files to serve through Nginx then caching of the files' metadata (not the actual files' contents) can save some latency.
  open_file_cache max=1000 inactive=20s;
  open_file_cache_valid 30s;
  open_file_cache_min_uses 2;
  open_file_cache_errors on;

  # 隐藏头部信息，格式为：proxy_hide_header 响应头部字段
  proxy_hide_header Vary;
  proxy_hide_header X-Powered-By;

######################## default ############################
   #http
   server {
    listen 80;
    # 服务器名
    server_name www.xxxx.com;
    
    # 重定向
    rewrite ^(.*) https://www.xxxx.com;
    
    # 访问日志
    access_log /www/LOG/access_nginx.log combined;

    # 默认主页
    index index.html index.htm index.php;

    # 错误页面，格式：error_page 错误码 错误页面路径
    #error_page 404 /404.html;
    #error_page 502 /502.html
    
    # http://www.xxxx.com/nginx_status查看nginx状态
    location /nginx_status {
      stub_status on;
      access_log off;
      allow 127.0.0.1; # 允许访问的ip
      deny all;   # 拒绝除allow之外的所有访问
    }

    # 转发PHP请求到php-fpm，[^/]匹配非/的字符
    location ~ [^/]\.php(/|$) {
      fastcgi_pass 127.0.0.1:9000; # 转发到本地9000端口，php-fpm默认端口
      #fastcgi_pass unix:/dev/shm/php-cgi.sock;
      fastcgi_index index.php;
      include fastcgi.conf;
    }
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
      expires 30d; # 规定时间后过期
      access_log off;
    }
    location ~ .*\.(js|css)?$ {
      expires 7d;
      access_log off;
    }
    location ~ /\.ht {
      deny all;
    }

  }

  #https 
  server{
    listen 443;
    server_name www.xxxx.com; 

    root  /www/website;
    index index.html index.htm index.php;
    access_log /www/LOG/access_nginx.log combined;

    # ssl配置
    ssl on;
    ssl_certificate &quot;xxxx.crt&quot;;
    ssl_certificate_key &quot;xxxx.key&quot;;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;   

    location /nginx_status {
      stub_status on;
      access_log off;
      allow 127.0.0.1;
      deny all;
    }
    location ~ [^/]\.php(/|$) {
      #fastcgi_pass 127.0.0.1:9000;
      fastcgi_pass unix:/dev/shm/php-cgi.sock;
      fastcgi_index index.php;
      include fastcgi.conf;
    }
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
      expires 30d;
      access_log off;
    } 
    location ~ .*\.(js|css)?$ {
      expires 7d;
      access_log off;
    } 
    location ~ /\.ht {
      deny all;
    } 
  }
########################## vhost #############################
  # 包含其他配置信息
  include vhost/*.conf;
}
</code></pre>

            </div>
            
            
              <div class="post-footer">
  <ul class="post-copyright">
    <li class="post-copyright-author">
      <strong class="language" data-lan="author">本文作者：</strong>
      anhoder
    </li>
    <li class="post-copyright-link">
      <strong class="language" data-lan="link">本文链接：</strong>
      <a href="/post/nQ_auU4ob/" title="Nginx服务器配置详解">/post/nQ_auU4ob/</a>
    </li>
    <li class="post-copyright-license">
      <strong class="language" data-lan="copyright">版权声明： </strong>
      本博客所有文章除特别声明外，均采用<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fa fa-fw fa-creative-commons"></i> BY-NC-SA</a> 许可协议。转载请注明出处！
    </li>
  </ul>
  <div class="tags">
    
      <a href="/tag/GEB4m1_Wa/"># Nginx</a>
    
  </div>
  <div class="nav">
    <div class="nav-prev">
      
        <i class="fa fa-chevron-left"></i>
        <a class="nav-pc-next" title="Node篇---（一）特点" href="/post/JYJs07YkE/">Node篇---（一）特点</a class="nav-pc-next">
        <a class="nav-mobile-prev" title="Node篇---（一）特点" href="/post/JYJs07YkE/">上一篇</a>
      
    </div>
    <div class="nav-next">
      
        <a class="nav-pc-next" title="Vue.js的数据绑定原理" href="/post/upmzqiH5w/">Vue.js的数据绑定原理</a>
        <a class="nav-mobile-next" title="Vue.js的数据绑定原理" href="/post/upmzqiH5w/">下一篇</a>
        <i class="fa fa-chevron-right"></i>
      
    </div>
  </div>
</div>
            
            
  
    
      <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
<script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>

<div id="gitalk-container"></div>

<script>
  var gitalk = new Gitalk({
    clientID: '8254f894b17fffeef6e2',
    clientSecret: 'aa345603999774a44649ad73ef7fe72ee45a021b',
    repo: 'personal-blog-comments',
    owner: 'anhoder',
    admin: ['anhoder'],
    id: (location.pathname).substring(0, 49),      // Ensure uniqueness and length less than 50
    distractionFreeMode: false  // Facebook-like distraction free mode
  })
  gitalk.render('gitalk-container')
</script>
    
    
  

          </div>
        </div>
      </div>
    </div>
    <div class="footer-box">
  <footer class="footer">
    <div class="poweredby">
      © Authored by <a href="https://github.com/anhoder">anhoder</a> since 2019.
    </div>
    <div class="copyright">
      Powered by <a href="https://github.com/getgridea/gridea" target="_blank">Gridea</a> | Theme By <a
        href="https://github.com/hsxyhao/gridea-theme-next" target="_blank">HsxyHao</a>
    </div>
  </footer>
  
  
  <div class="pisces back-to-top" id="back_to_top">
    <i class="fa fa-arrow-up"></i>
    
    <span class="scrollpercent">
      <span id="back_to_top_text">0</span>%
    </span>
    
  </div>
  
  
  
<link rel="stylesheet" href="/media/live2d/css/live2d.css" />
<div class="box-scale">
  <div id="landlord" style="left: 100%px;bottom: 100%px;"
    data-key="">
    <canvas id="live2d" width="500" height="560" class="live2d"></canvas>
    
  </div>
</div>
<div id="open_live2d">召唤看板娘</div>
<script src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
  var message_Path = 'https://cdn.jsdelivr.net/gh/anhoder/source-for-blog@master/';
  let landlord = document.querySelector('#landlord');
  var apiKey = landlord.dataset.key;
</script>
<script type="text/javascript" src="/media/live2d/js/live2d.js"></script>
<script>
	var home_Path = document.location.protocol + '//' + window.document.location.hostname + ":" + window.document.location.port + '/';
	var userAgent = window.navigator.userAgent.toLowerCase();
	var norunAI = ["android", "iphone", "ipod", "ipad", "windows phone", "mqqbrowser", "msie", "trident/7.0"];
	var norunFlag = false;

	for (var i = 0; i < norunAI.length; i++) {
		if (userAgent.indexOf(norunAI[i]) > -1) {
			norunFlag = true;
			break;
		}
	}

	if (!window.WebGLRenderingContext) {
		norunFlag = true;
	}

	if (!norunFlag) {
		var hitFlag = false;
		var AIFadeFlag = false;
		var liveTlakTimer = null;
		var sleepTimer_ = null;
		var AITalkFlag = false;
		var talkNum = 0;
		(function () {
			function renderTip(template, context) {
				var tokenReg = /(\\)?\{([^\{\}\\]+)(\\)?\}/g;
				return template.replace(tokenReg, function (word, slash1, token, slash2) {
					if (slash1 || slash2) {
						return word.replace('\\', '');
					}
					var variables = token.replace(/\s/g, '').split('.');
					var currentObject = context;
					var i, length, variable;
					for (i = 0, length = variables.length; i < length; ++i) {
						variable = variables[i];
						currentObject = currentObject[variable];
						if (currentObject === undefined || currentObject === null) return '';
					}
					return currentObject;
				});
			}

			String.prototype.renderTip = function (context) {
				return renderTip(this, context);
			};

			var re = /x/;
			re.toString = function () {
				showMessage('哈哈，你打开了控制台，是想要看看我的秘密吗？', 5000);
				return '';
			};

			$(document).on('copy', function () {
				showMessage('你都复制了些什么呀，转载要记得加上出处哦~~', 5000);
			});

			function initTips() {
				$.ajax({
					cache: true,
					url: message_Path + 'message.json',
					dataType: "json",
					success: function (result) {
						$.each(result.mouseover, function (index, tips) {
							$(tips.selector).mouseover(function () {
								var text = tips.text;
								if (Array.isArray(tips.text)) text = tips.text[Math.floor(Math.random() * tips.text.length + 1) - 1];
								text = text.renderTip({ text: $(this).text() });
								showMessage(text, 3000);
								talkValTimer();
								clearInterval(liveTlakTimer);
								liveTlakTimer = null;
							});
							$(tips.selector).mouseout(function () {
								showHitokoto();
								if (liveTlakTimer == null) {
									liveTlakTimer = window.setInterval(function () {
										showHitokoto();
									}, 15000);
								};
							});
						});
						$.each(result.click, function (index, tips) {
							$(tips.selector).click(function () {
								if (hitFlag) {
									return false
								}
								hitFlag = true;
								setTimeout(function () {
									hitFlag = false;
								}, 8000);
								var text = tips.text;
								if (Array.isArray(tips.text)) text = tips.text[Math.floor(Math.random() * tips.text.length + 1) - 1];
								text = text.renderTip({ text: $(this).text() });
								showMessage(text, 3000);
							});
							clearInterval(liveTlakTimer);
							liveTlakTimer = null;
							if (liveTlakTimer == null) {
								liveTlakTimer = window.setInterval(function () {
									showHitokoto();
								}, 15000);
							};
						});
					}
				});
			}
			initTips();

			var text;
			if (document.referrer !== '') {
				var referrer = document.createElement('a');
				referrer.href = document.referrer;
				text = '嗨！来自 <span style="color:#0099cc;">' + referrer.hostname + '</span> 的朋友！';
				var domain = referrer.hostname.split('.')[1];
				if (domain == 'baidu') {
					text = '嗨！ 来自 百度搜索 的朋友！<br>欢迎访问<span style="color:#0099cc;">「 ' + document.title.split(' - ')[0] + ' 」</span>';
				} else if (domain == 'so') {
					text = '嗨！ 来自 360搜索 的朋友！<br>欢迎访问<span style="color:#0099cc;">「 ' + document.title.split(' - ')[0] + ' 」</span>';
				} else if (domain == 'google') {
					text = '嗨！ 来自 谷歌搜索 的朋友！<br>欢迎访问<span style="color:#0099cc;">「 ' + document.title.split(' - ')[0] + ' 」</span>';
				}
			} else {
				if (window.location.href == home_Path) { //主页URL判断，需要斜杠结尾
					var now = (new Date()).getHours();
					if (now > 23 || now <= 5) {
						text = '你是夜猫子呀？这么晚还不睡觉，明天起的来嘛？';
					} else if (now > 5 && now <= 7) {
						text = '早上好！一日之计在于晨，美好的一天就要开始了！';
					} else if (now > 7 && now <= 11) {
						text = '上午好！工作顺利嘛，不要久坐，多起来走动走动哦！';
					} else if (now > 11 && now <= 14) {
						text = '中午了，工作了一个上午，现在是午餐时间！';
					} else if (now > 14 && now <= 17) {
						text = '午后很容易犯困呢，今天的运动目标完成了吗？';
					} else if (now > 17 && now <= 19) {
						text = '傍晚了！窗外夕阳的景色很美丽呢，最美不过夕阳红~~';
					} else if (now > 19 && now <= 21) {
						text = '晚上好，今天过得怎么样？';
					} else if (now > 21 && now <= 23) {
						text = '已经这么晚了呀，早点休息吧，晚安~~';
					} else {
						text = '嗨~ 快来逗我玩吧！';
					}
				} else {
					text = '欢迎阅读<span style="color:#0099cc;">「 ' + document.title.split(' - ')[0] + ' 」</span>';
				}
			}
			showMessage(text, 12000);
		})();

		liveTlakTimer = setInterval(function () {
			showHitokoto();
		}, 15000);

		function showHitokoto() {
			if (sessionStorage.getItem("Sleepy") !== "1") {
				if (!AITalkFlag) {
					$.getJSON('https://v1.hitokoto.cn/', function (result) {
						talkValTimer();
						showMessage(result.hitokoto, 0);
					});
				}
			} else {
				hideMessage(0);
				if (sleepTimer_ == null) {
					sleepTimer_ = setInterval(function () {
						checkSleep();
					}, 200);
				}
			}
		}

		function checkSleep() {
			var sleepStatu = sessionStorage.getItem("Sleepy");
			if (sleepStatu !== '1') {
				talkValTimer();
				showMessage('你回来啦~', 0);
				clearInterval(sleepTimer_);
				sleepTimer_ = null;
			}
		}

		function showMessage(text, timeout) {
			if (Array.isArray(text)) text = text[Math.floor(Math.random() * text.length + 1) - 1];
			$('.message').stop();
			$('.message').html(text);
			$('.message').fadeTo(200, 1);
			//if (timeout === null) timeout = 5000;
			//hideMessage(timeout);
		}
		function talkValTimer() {
			$('#live_talk').val('1');
		}

		function hideMessage(timeout) {
			//$('.message').stop().css('opacity',1);
			if (timeout === null) timeout = 5000;
			$('.message').delay(timeout).fadeTo(200, 0);
		}

		function initLive2d() {
			$('#hideButton').on('click', function () {
				if (AIFadeFlag) {
					return false;
				} else {
					AIFadeFlag = true;
					localStorage.setItem("live2dhidden", "0");
					$('#landlord').fadeOut(200);
					$('#open_live2d').delay(200).fadeIn(200);
					setTimeout(function () {
						AIFadeFlag = false;
					}, 300);
				}
			});
			$('#open_live2d').on('click', function () {
				if (AIFadeFlag) {
					return false;
				} else {
					AIFadeFlag = true;
					localStorage.setItem("live2dhidden", "1");
					$('#open_live2d').fadeOut(200);
					$('#landlord').delay(200).fadeIn(200);
					setTimeout(function () {
						AIFadeFlag = false;
					}, 300);
				}
			});
			$('#youduButton').on('click', function () {
				if ($('#youduButton').hasClass('doudong')) {
					var typeIs = $('#youduButton').attr('data-type');
					$('#youduButton').removeClass('doudong');
					$('body').removeClass(typeIs);
					$('#youduButton').attr('data-type', '');
				} else {
					var duType = $('#duType').val();
					var duArr = duType.split(",");
					var dataType = duArr[Math.floor(Math.random() * duArr.length)];

					$('#youduButton').addClass('doudong');
					$('#youduButton').attr('data-type', dataType);
					$('body').addClass(dataType);
				}
			});
			if (apiKey) {
				$('#showInfoBtn').on('click', function () {
					var live_statu = $('#live_statu_val').val();
					if (live_statu == "0") {
						return
					} else {
						$('#live_statu_val').val("0");
						$('.live_talk_input_body').fadeOut(500);
						AITalkFlag = false;
						showHitokoto();
						$('#showTalkBtn').show();
						$('#showInfoBtn').hide();
					}
				});
				$('#showTalkBtn').on('click', function () {
					var live_statu = $('#live_statu_val').val();
					if (live_statu == "1") {
						return
					} else {
						$('#live_statu_val').val("1");
						$('.live_talk_input_body').fadeIn(500);
						AITalkFlag = true;
						$('#showTalkBtn').hide();
						$('#showInfoBtn').show();

					}
				});
				$('#talk_send').on('click', function () {
					var info_ = $('#AIuserText').val();
					var userid_ = $('#AIuserName').val();
					if (info_ == "") {
						showMessage('写点什么吧！', 0);
						return;
					}
					if (userid_ == "") {
						showMessage('聊之前请告诉我你的名字吧！', 0);
						return;
					}
					showMessage('思考中~', 0);
					let protocol = window.location.protocol.indexOf("s") > 0 ? "https" : "http";
					$.ajax({
						type: "get",
						url: `${protocol}://www.tuling123.com/openapi/api?key=${apiKey}&info=${info_}`,
						dataType: "json",
						success: function (res) {
							talkValTimer();
							showMessage(res.text, 0);
							$('#AIuserText').val("");
							sessionStorage.setItem("live2duser", userid_);
						},
						error: function (e) {
							talkValTimer();
							showMessage('似乎有什么错误，请和站长联系！', 0);
						}
					});
				});
			} else {
				$('#showInfoBtn').hide();
				$('#showTalkBtn').hide();
			}
			//获取音乐信息初始化
			var bgmListInfo = $('input[name=live2dBGM]');
			if (bgmListInfo.length == 0) {
				$('#musicButton').hide();
			} else {
				var bgmPlayNow = parseInt($('#live2d_bgm').attr('data-bgm'));
				var bgmPlayTime = 0;
				var live2dBGM_Num = sessionStorage.getItem("live2dBGM_Num");
				var live2dBGM_PlayTime = sessionStorage.getItem("live2dBGM_PlayTime");
				if (live2dBGM_Num) {
					if (live2dBGM_Num <= $('input[name=live2dBGM]').length - 1) {
						bgmPlayNow = parseInt(live2dBGM_Num);
					}
				}
				if (live2dBGM_PlayTime) {
					bgmPlayTime = parseInt(live2dBGM_PlayTime);
				}
				var live2dBGMSrc = bgmListInfo.eq(bgmPlayNow).val();
				$('#live2d_bgm').attr('data-bgm', bgmPlayNow);
				$('#live2d_bgm').attr('src', live2dBGMSrc);
				$('#live2d_bgm')[0].currentTime = bgmPlayTime;
				$('#live2d_bgm')[0].volume = 0.5;
				var live2dBGM_IsPlay = sessionStorage.getItem("live2dBGM_IsPlay");
				var live2dBGM_WindowClose = sessionStorage.getItem("live2dBGM_WindowClose");
				if (live2dBGM_IsPlay == '0' && live2dBGM_WindowClose == '0') {
					$('#live2d_bgm')[0].play();
					$('#musicButton').addClass('play');
				}
				sessionStorage.setItem("live2dBGM_WindowClose", '1');
				$('#musicButton').on('click', function () {
					if ($('#musicButton').hasClass('play')) {
						$('#live2d_bgm')[0].pause();
						$('#musicButton').removeClass('play');
						sessionStorage.setItem("live2dBGM_IsPlay", '1');
					} else {
						$('#live2d_bgm')[0].play();
						$('#musicButton').addClass('play');
						sessionStorage.setItem("live2dBGM_IsPlay", '0');
					}
				});
				window.onbeforeunload = function () {
					sessionStorage.setItem("live2dBGM_WindowClose", '0');
					if ($('#musicButton').hasClass('play')) {
						sessionStorage.setItem("live2dBGM_IsPlay", '0');
					}
				}
				document.getElementById('live2d_bgm').addEventListener("timeupdate", function () {
					var live2dBgmPlayTimeNow = document.getElementById('live2d_bgm').currentTime;
					sessionStorage.setItem("live2dBGM_PlayTime", live2dBgmPlayTimeNow);
				});
				document.getElementById('live2d_bgm').addEventListener("ended", function () {
					var listNow = parseInt($('#live2d_bgm').attr('data-bgm'));
					listNow++;
					if (listNow > $('input[name=live2dBGM]').length - 1) {
						listNow = 0;
					}
					var listNewSrc = $('input[name=live2dBGM]').eq(listNow).val();
					sessionStorage.setItem("live2dBGM_Num", listNow);
					$('#live2d_bgm').attr('src', listNewSrc);
					$('#live2d_bgm')[0].play();
					$('#live2d_bgm').attr('data-bgm', listNow);
				});
				document.getElementById('live2d_bgm').addEventListener("error", function () {
					$('#live2d_bgm')[0].pause();
					$('#musicButton').removeClass('play');
					showMessage('音乐似乎加载不出来了呢！', 0);
				});
			}
			//获取用户名
			var live2dUser = sessionStorage.getItem("live2duser");
			if (live2dUser !== null) {
				$('#AIuserName').val(live2dUser);
			}
			//获取位置
			var landL = sessionStorage.getItem("historywidth");
			var landB = sessionStorage.getItem("historyheight");
			if (landL == null || landB == null) {
				landL = '5px'
				landB = '0px'
			}
			$('#landlord').css('left', landL + 'px');
			$('#landlord').css('bottom', landB + 'px');
			//移动
			function getEvent() {
				return window.event || arguments.callee.caller.arguments[0];
			}
			var smcc = document.getElementById("landlord");
			var moveX = 0;
			var moveY = 0;
			var moveBottom = 0;
			var moveLeft = 0;
			var moveable = false;
			var docMouseMoveEvent = document.onmousemove;
			var docMouseUpEvent = document.onmouseup;
			smcc.onmousedown = function () {
				var ent = getEvent();
				moveable = true;
				moveX = ent.clientX;
				moveY = ent.clientY;
				var obj = smcc;
				moveBottom = parseInt(obj.style.bottom);
				moveLeft = parseInt(obj.style.left);
				if (isFirefox = navigator.userAgent.indexOf("Firefox") > 0) {
					window.getSelection().removeAllRanges();
				}
				document.onmousemove = function () {
					if (moveable) {
						var ent = getEvent();
						var x = moveLeft + ent.clientX - moveX;
						var y = moveBottom + (moveY - ent.clientY);
						obj.style.left = x + "px";
						obj.style.bottom = y + "px";
					}
				};
				document.onmouseup = function () {
					if (moveable) {
						var historywidth = obj.style.left;
						var historyheight = obj.style.bottom;
						historywidth = historywidth.replace('px', '');
						historyheight = historyheight.replace('px', '');
						sessionStorage.setItem("historywidth", historywidth);
						sessionStorage.setItem("historyheight", historyheight);
						document.onmousemove = docMouseMoveEvent;
						document.onmouseup = docMouseUpEvent;
						moveable = false;
						moveX = 0;
						moveY = 0;
						moveBottom = 0;
						moveLeft = 0;
					}
				};
			};
		}
		$(document).ready(function () {
			var AIimgSrc = [];
			let chooseLive2d = 'plt'
			if (chooseLive2d === 'histoire') {
				AIimgSrc.push(message_Path + "model/histoire/histoire.1024/texture_00.png");
				AIimgSrc.push(message_Path + "model/histoire/histoire.1024/texture_01.png");
				AIimgSrc.push(message_Path + "model/histoire/histoire.1024/texture_02.png");
				AIimgSrc.push(message_Path + "model/histoire/histoire.1024/texture_03.png");
			} else if (chooseLive2d === 'rem') {
				AIimgSrc.push(message_Path + "model/rem/remu2048/texture_00.png");
			} else if (chooseLive2d === 'aoba') {
				AIimgSrc.push(message_Path + "model/aoba/textures/texture_00.png");
			} else if (chooseLive2d === 'hijiki') {
				AIimgSrc.push(message_Path + "model/hijiki/moc/hijiki.2048/texture_00.png");
			} else if (chooseLive2d === 'tororo') {
				AIimgSrc.push(message_Path + "model/tororo/moc/tororo.2048/texture_00.png");
			} else if (chooseLive2d === 'plt') {
				AIimgSrc.push(message_Path + "model/plt/moc/plt.2048/texture_00.png");
			}
			var images = [];
			var imgLength = AIimgSrc.length;
			var loadingNum = 0;
			for (var i = 0; i < imgLength; i++) {
				images[i] = new Image();
				images[i].src = AIimgSrc[i];
				images[i].onload = function () {
					loadingNum++;
					if (loadingNum === imgLength) {
						var live2dhidden = localStorage.getItem("live2dhidden");
						if (live2dhidden === "0") {
							setTimeout(function () {
								$('#open_live2d').fadeIn(200);
							}, 1300);
						} else {
							setTimeout(function () {
								$('#landlord').fadeIn(200);
							}, 1300);
						}
						let model = '';
						if (chooseLive2d === 'histoire') {
							model = message_Path + "model/histoire/model.json";
						} else if (chooseLive2d === 'rem') {
							model = message_Path + "model/rem/model.json";
						} else if (chooseLive2d === 'aoba') {
							model = message_Path + "model/aoba/model.json";
						} else if (chooseLive2d === 'hijiki') {
							model = message_Path + "model/hijiki/hijiki.model.json";
						} else if (chooseLive2d === 'tororo') {
							model = message_Path + "model/tororo/tororo.model.json";
						} else if (chooseLive2d === 'plt') {
							model = message_Path + "model/plt/model.json?v=1617466520";
						}
						setTimeout(function () {
							loadlive2d("live2d", model);
						}, 1000);
						initLive2d();
						images = null;
					}
				}
			}
		});
	}
</script>
  
  
</div>
<script>

  let sideBarOpen = 'sidebar-open';
  let body = document.body;
  let back2Top = document.querySelector('#back_to_top'),
    back2TopText = document.querySelector('#back_to_top_text'),
    drawerBox = document.querySelector('#drawer_box'),
    rightSideBar = document.querySelector('.sidebar'),
    viewport = document.querySelector('body');

  function scrollAnimation(currentY, targetY) {

    let needScrollTop = targetY - currentY
    let _currentY = currentY
    setTimeout(() => {
      const dist = Math.ceil(needScrollTop / 10)
      _currentY += dist
      window.scrollTo(_currentY, currentY)
      if (needScrollTop > 10 || needScrollTop < -10) {
        scrollAnimation(_currentY, targetY)
      } else {
        window.scrollTo(_currentY, targetY)
      }
    }, 1)
  }

  back2Top.addEventListener("click", function (e) {
    scrollAnimation(document.scrollingElement.scrollTop, 0);
    e.stopPropagation();
    return false;
  });

  window.addEventListener('scroll', function (e) {
    let percent = document.scrollingElement.scrollTop / (document.scrollingElement.scrollHeight - document.scrollingElement.clientHeight) * 100;
    if (percent > 1 && !back2Top.classList.contains('back-top-active')) {
      back2Top.classList.add('back-top-active');
    }
    if (percent == 0) {
      back2Top.classList.remove('back-top-active');
    }
    if (back2TopText) {
      back2TopText.textContent = Math.floor(percent);
    }
  });


  let hasCacu = false;
  window.onresize = function () {
    calcuHeight();
  }

  function calcuHeight() {
    // 动态调整站点概览高度
    if (!hasCacu && back2Top.classList.contains('pisces') || back2Top.classList.contains('gemini')) {
      let sideBar = document.querySelector('.sidebar');
      let navUl = document.querySelector('#site_nav');
      sideBar.style = 'margin-top:' + (navUl.offsetHeight + navUl.offsetTop + 15) + 'px;';
      hasCacu = true;
    }
  }
  calcuHeight();

  let open = false, MOTION_TIME = 300, RIGHT_MOVE_DIS = '320px';

  if (drawerBox) {
    let rightMotions = document.querySelectorAll('.right-motion');
    let right = drawerBox.classList.contains('right');

    let transitionDir = right ? "transition.slideRightIn" : "transition.slideLeftIn";

    let openProp, closeProp;
    if (right) {
      openProp = {
        paddingRight: RIGHT_MOVE_DIS
      };
      closeProp = {
        paddingRight: '0px'
      };
    } else {
      openProp = {
        paddingLeft: RIGHT_MOVE_DIS
      };
      closeProp = {
        paddingLeft: '0px'
      };
    }

    drawerBox.onclick = function () {
      open = !open;
      window.Velocity(rightSideBar, 'stop');
      window.Velocity(viewport, 'stop');
      window.Velocity(rightMotions, 'stop');
      if (open) {
        window.Velocity(rightSideBar, {
          width: RIGHT_MOVE_DIS
        }, {
          duration: MOTION_TIME,
          begin: function () {
            window.Velocity(rightMotions, transitionDir, {});
          }
        })
        window.Velocity(viewport, openProp, {
          duration: MOTION_TIME
        });
      } else {
        window.Velocity(rightSideBar, {
          width: '0px'
        }, {
          duration: MOTION_TIME,
          begin: function () {
            window.Velocity(rightMotions, {
              opacity: 0
            });
          }
        })
        window.Velocity(viewport, closeProp, {
          duration: MOTION_TIME
        });
      }
      for (let i = 0; i < drawerBox.children.length; i++) {
        drawerBox.children[i].classList.toggle('muse-line');
      }
      drawerBox.classList.toggle(sideBarOpen);
    }
  }

  // 链接跳转
  let newWindow = 'false'
  if (newWindow === 'true') {
    let links = document.querySelectorAll('.post-body a')
    links.forEach(item => {
      if (!item.classList.contains('btn')) {
        item.setAttribute("target", "_blank");
      }
    })
  }

  let faSearch = document.querySelector('#fa_search');
  faSearch && faSearch.addEventListener('click', function () {
    document.querySelector('#search_mask').style = ''
  })

  // 代码高亮
  hljs.initHighlightingOnLoad();
  
  // 离开当前页title变化
  var leaveTitle = "";
  if (leaveTitle) {
    document.addEventListener('visibilitychange', function () {
      if (document.visibilityState == 'hidden') {
        normal_title = document.title;
        document.title = leaveTitle;
      } else {
        document.title = normal_title;
      }
    });
  }

</script>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>

<script>
  let images = document.querySelectorAll('.section img');
  console.log(images);
  images.forEach(image => {
    if (image.classList.contains('no-fancybox')) {
      return;
    }

    var parent = image.parentElement;
    var next = image.nextElementSibling;
    parent.removeChild(image);
    var aelem = document.createElement('a');
    aelem.href = image.src;
    aelem.dataset['fancybox'] = 'images';
    aelem.dataset['rel'] = 'fancybox-button';
    aelem.classList.add('fancybox');
    aelem.appendChild(image);
    parent.insertBefore(aelem, next);
  })
</script>
    <div class="reward-mask" style="display: none;">
  <div class="reward-relative">
    <span class="close" aria-hidden="true">x</span>
    <div class="reward-body">
      <h2>感谢您的支持，我会继续努力的!</h2>
      <div class="reward-img-box">
        <div style="position: relative; width: 140px; height: 140px;">
          
          
          
        </div>
      </div>
      <p class="reward-word">扫码打赏，你说多少就多少</p>
      <p class="reward-tip">打开微信扫一扫，即可进行扫码打赏哦</p>
    </div>
    <div class="bottom">
      
      
    </div>
  </div>
</div>
<style>
  .reward-mask {
    position: fixed;
    z-index: 99999;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: #00000054;
  }

  .reward-relative {
    position: relative;
    width: 480px;
    text-align: center;
    margin: 0 auto;
    border-radius: 5px;
    background-color: #fff;
    top: 50%;
    margin-top: -205px;
  }

  .reward-relative .close {
    position: absolute;
    right: 10px;
    font-weight: normal;
    font-size: 16px;
    color: #929292;
  }

  .reward-body {
    padding: 40px 20px 20px;
  }

  .bottom {
    display: flex;
  }

  .reward-btn {
    text-align: center;
  }

  .reward-btn-text {
    display: inline-block;
    cursor: pointer;
    width: 60px;
    height: 60px;
    line-height: 60px;
    border-radius: 50%;
    background-color: #ff9734;
    color: #FFF;
    margin-top: 20px;
  }

  .pay-text {
    margin-top: 10px;
    padding: 10px;
    flex: 1;
    transition: all .2s linear;
  }

  .pay-text:hover {
    background-color: #a5a5a536;
  }

  .reward-body h2 {
    padding-top: 10px;
    text-align: center;
    color: #a3a3a3;
    font-size: 16px;
    font-weight: normal;
    margin: 0 0 20px;
  }

  .reward-body h2:after,
  .reward-body h2:before {
    font-family: Arial, Helvetica, sans-serif;
    background: 0 0;
    width: 0;
    height: 0;
    font-style: normal;
    color: #eee;
    font-size: 80px;
    position: absolute;
    top: 20px;
  }

  .reward-body h2:before {
    content: '\201c';
    left: 50px;
  }

  .reward-body h2:after {
    content: '\201d';
    right: 80px;
  }

  .reward-img-box {
    display: inline-block;
    padding: 10px;
    border: 6px solid #ea5f00;
    margin: 0 auto;
    border-radius: 3px;
    position: relative;
  }

  .reward-img {
    position: absolute;
    left: 0px;
    top: 0px;
    width: 100%;
    height: 100%;
  }

  @media (max-width: 767px) {
    .reward-relative {
      height: 100%;
      top: 0px;
      margin-top: 0;
      width: auto;
    }

    .reward-relative .bottom {
      flex-direction: column;
    }

    .reward-relative .pay-text {
      width: 80%;
      margin: 5px auto;
      border: 1px solid silver;
      padding: 6px;
      border-radius: 4px;
    }

    .reward-body h2:after {
      right: 40px;
    }

    .reward-body h2:after,
    .reward-body h2:before {
      font-size: 60px;
    }

    .reward-body h2:before {
      left: 20px;
    }
  }
</style>
<script>
  !function () {
    var mask = document.querySelector('.reward-mask');
    let close = document.querySelector('.reward-relative .close');
    let rewardBtn = document.querySelector('.reward-btn');

    let zfb = document.querySelector('#zfb'),
      wx = document.querySelector('#wx'),
      zfbBtn = document.querySelector('#zfbBtn'),
      wxBtn = document.querySelector('#wxBtn');

    if (zfbBtn && wxBtn) {
      zfbBtn.addEventListener('click', () => {
        window.Velocity(zfb, 'transition.slideLeftIn', {
          duration: 400
        });
        window.Velocity(wx, 'transition.slideRightOut', {
          display: 'none',
          duration: 400
        });
      });

      wxBtn.addEventListener('click', () => {
        window.Velocity(wx, 'transition.slideRightIn', {
          duration: 400
        });
        window.Velocity(zfb, 'transition.slideLeftOut', {
          display: 'none',
          duration: 400
        });
      });
    }

    rewardBtn && rewardBtn.addEventListener('click', (e) => {
      window.Velocity(mask, 'transition.slideDownIn', {
        duration: 400
      })
    });

    close.addEventListener('click', (e) => {
      e.preventDefault();
      window.Velocity(mask, 'transition.slideUpOut', {
        duration: 400
      })
    })
  }()
</script>

  </div>
</body>

<input hidden id="copy" />
<script>
  !function () {
    let times = document.querySelectorAll('.publish-time');
    for (let i = 0; i < times.length; i++) {
      let date = times[i].dataset.t;
      let time = Math.floor((new Date().getTime() - new Date(date).getTime()) / 1000);
      if (time < 60) {
        str = time + '秒之前';
      } else if (time < 3600) {
        str = Math.floor(time / 60) + '分钟之前';
      } else if (time >= 3600 && time < 86400) {
        str = Math.floor(time / 3600) + '小时之前';
      } else if (time >= 86400 && time < 259200) {
        str = Math.floor(time / 86400) + '天之前';
      } else {
        str = times[i].textContent;
      }
      times[i].textContent = str;
    }
  }();
</script>

<script>
  let language = '';
  if (language !== '') {
    let map = new Map();
    if (language === 'en') {
      map.set('search', 'Search');
      map.set('category', 'Categories');
      map.set('article', 'Articles');
      map.set('tag', 'Tags');
      map.set('top', 'Top');
      map.set('publish', 'published');
      map.set('minute', ' minutes');
      map.set('read-more', 'Read More');
      map.set('view', 'View');
      map.set('words', ' words');
      map.set('category-in', 'category in');
      map.set('preview', 'Meta');
      map.set('index', 'Toc');
      map.set('no-archives', "You haven't created yet");
      map.set('archives', " articles in total");
      map.set('cloud-tags', " tags in total");
      map.set('copyright', "Copyright: ");
      map.set('author', "Author: ");
      map.set('link', "Link: ");
      map.set('leave-message', "Leave a message");
      map.set('format', "Links Format");
      map.set('site-name', "Name: ");
      map.set('site-link', "Link: ");
      map.set('site-desc', "Desc: ");
      map.set('stat', " related results, taking ");
      map.set('stat-time', " ms");
      map.set('site-img', "Image: ");
    }

    if (map.size > 0) {
      let lanElems = document.querySelectorAll('.language');
      lanElems.forEach(elem => {
        let lan = elem.dataset.lan, text = map.get(lan);
        if (elem.__proto__ === HTMLInputElement.prototype) {
          elem.placeholder = text
        } else {
          if (elem.dataset.count) {
            text = elem.dataset.count + text;
          }
          elem.textContent = text;
        }
      })
    }
  }
  //拿来主义(真香)^_^，Clipboard 实现摘自掘金 https://juejin.im/post/5aefeb6e6fb9a07aa43c20af
  window.Clipboard = (function (window, document, navigator) {
    var textArea,
      copy;

    // 判断是不是ios端
    function isOS() {
      return navigator.userAgent.match(/ipad|iphone/i);
    }
    //创建文本元素
    function createTextArea(text) {
      textArea = document.createElement('textArea');
      textArea.value = text;
      textArea.style.width = 0;
      textArea.style.height = 0;
      textArea.clientHeight = 0;
      textArea.clientWidth = 0;
      document.body.appendChild(textArea);
    }
    //选择内容
    function selectText() {
      var range,
        selection;

      if (isOS()) {
        range = document.createRange();
        range.selectNodeContents(textArea);
        selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
        textArea.setSelectionRange(0, 999999);
      } else {
        textArea.select();
      }
    }

    //复制到剪贴板
    function copyToClipboard() {
      try {
        document.execCommand("Copy")
      } catch (err) {
        alert("复制错误！请手动复制！")
      }
      document.body.removeChild(textArea);
    }

    copy = function (text) {
      createTextArea(text);
      selectText();
      copyToClipboard();
    };

    return {
      copy: copy
    };
  })(window, document, navigator);

  function copyCode(e) {
    if (e.srcElement.tagName === 'SPAN' && e.srcElement.classList.contains('copy-code')) {
      let code = e.currentTarget.querySelector('code');
      var text = code.innerText;
      if (e.srcElement.textContent === '复制成功') {
        return;
      }
      e.srcElement.textContent = '复制成功';
      (function (elem) {
        setTimeout(() => {
          if (elem.textContent === '复制成功') {
            elem.textContent = '复制代码'
          }
        }, 1000);
      })(e.srcElement)
      Clipboard.copy(text);
    }
  }

  let pres = document.querySelectorAll('pre');
  pres.forEach(pre => {
    let code = pre.querySelector('code');
    let copyElem = document.createElement('span');
    copyElem.classList.add('copy-code');
    copyElem.textContent = '复制代码';
    pre.appendChild(copyElem);
    pre.onclick = copyCode
  })

</script>
<script src="/media/js/motion.js"></script>


<script src="https://cdn.jsdelivr.net/gh/cferdinandi/smooth-scroll/dist/smooth-scroll.polyfills.min.js"></script>
<script>
  var scroll = new SmoothScroll('a[href*="#"]', {
    speed: 200
  });
</script>



<script src="/media/js/cool.js"></script>



</html>